<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>没有闭包的局限性(The limitations of not having a closure)</title>
  <!-- 
  在JavaScript中，闭包（Closure）是一个重要的概念，它允许函数访问其外部作用域的变量，即使在外部函数已经返回的情况下。如果没有闭包，JavaScript中的一些功能和特性将受到限制。
  一、无法保持状态
  - 状态管理：闭包允许函数保持对其外部作用域变量的引用。如果没有闭包，函数在执行结束后将无法访问其外部作用域的变量，导致无法保持状态。

    如果没有闭包，以下代码无法正常工作：
  function createCounter() {
        let count = 0; // 外部变量
        return function() {
            count += 1; // 访问外部变量
            return count;
        };
    }

    const counter = createCounter();
    console.log(counter()); // 输出: 1
    console.log(counter()); // 输出: 2
  如果没有闭包， `count` 变量在 `createCounter` 函数执行完后就无法访问了。

  二、无法实现数据封装
  - 数据私有性：闭包可以用于创建私有变量，防止外部代码直接访问和修改这些变量。如果没有闭包，所有变量都是全局可见的，可能导致命名冲突和意外修改。

    没有闭包的情况下，无法实现数据封装：
    function Counter() {
        this.count = 0; // 公开变量
    }

    Counter.prototype.increment = function() {
        this.count += 1;
    };

    const counter = new Counter();
    counter.increment();
    console.log(counter.count); // 输出: 1
  在这个例子中， `count` 是公开的，任何代码都可以直接访问和修改它。

  三、无法创建工厂函数
  - 工厂函数：闭包使得可以创建工厂函数，返回具有独立状态的多个实例。如果没有闭包，每个实例都无法保持自己的状态。

    如果没有闭包，无法创建具有独立状态的实例：
    function createPerson(name) {
      return {
        getName: function() {
          return name; // 访问外部变量
        }
      };
    }

    const person1 = createPerson('Alice');
    const person2 = createPerson('Bob');
    console.log(person1.getName()); // 输出: Alice
    console.log(person2.getName()); // 输出: Bob
  在没有闭包的情况下， `name` 变量在 `createPerson` 执行后就无法访问。

  四、无法实现回调函数的上下文
  - 回调函数中的上下文：闭包允许回调函数访问其创建时的上下文。如果没有闭包，回调函数可能无法访问所需的上下文变量。
    function setupButton(buttonId) {
      let button = document.getElementById(buttonId);
      button.addEventListener('click', function() {
        console.log('Button clicked: ' + buttonId); // 访问外部变量
      });
    }

    setupButton('myButton');
  如果没有闭包， `buttonId` 在回调函数中将不可用。

  五、总结
  - 状态管理：没有闭包，无法保持函数的状态。
  - 数据封装：无法实现私有变量，导致数据泄露和命名冲突。
  - 工厂函数：无法创建具有独立状态的多个实例。
  - 上下文访问：回调函数无法访问创建时的上下文。
   -->
</head>
<body>

  <script>

    // 1. 无法保持函数的状态
    function counter() {
      let count = 0;
      return function() {
        count++;
        console.log(count);
      };
    }

    const increment = counter();
    increment(); // 输出: 1
    increment(); // 输出: 2
    increment(); // 输出: 3

    // 2. 无法实现私有变量，导致数据泄露和命名冲突
    function createPerson(name) {
      return {
        getName: function() {
          return name;
        }
      };
    }

    const person1 = createPerson('Alice');
    const person2 = createPerson('Bob');
    console.log(person1.getName()); // 输出: Alice

    // 3. 无法创建具有独立状态的多个实例
    function createCounter() {
      let count = 0;
      return {
        increment: function() {
          count++;
          console.log(count);
        }
      };
    }

    const counter1 = createCounter();
    const counter2 = createCounter();
    counter1.increment(); // 输出: 1
    counter2.increment(); // 输出: 1

    // 4. 回调函数无法访问创建时的上下文
    function setupButton(buttonId) {
      let button = document.getElementById(buttonId); // 假设这个函数在DOM加载后调用
      button.addEventListener('click', function() {
        console.log(`Button ${buttonId} clicked`);
      });
    }

    setupButton('button1');

    // 5. 无法在函数外部访问函数内部的变量
    var name = "why"
    var age = 18
    var height = 1.88
    var address = "广州市"
    var intro = "了解真相, 你才能获得真正自由!"
    
    function foo(name, age, height, address, intro, num1, num2) {
      var message = "Hello World"
      console.log(message, name, age, height, address, intro)

      function bar() {
        console.log(name)
      }

      bar()
    }

    foo(name, age, height, address, intro, 20, 30)

  </script>
  
</body>
</html>